package com.swingson.properties.specificclass_impl;

import com.swingson.SwingsonGui;
import com.swingson.event.ValueEvent;
import com.swingson.jsonparser.JsonElement;
import com.swingson.other.ConditionAndAction;
import com.swingson.other.MethodExecutor;
import com.swingson.properties.AbstractAssignMethodPropertyProcessor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.TransferHandler;

/**
 * @author sad
 */
public class OnFileDropPropertyProcessor extends AbstractAssignMethodPropertyProcessor {

    static List<Class[]> argumentsVariants = new ArrayList<Class[]>() {
        {
            add(new Class[]{File.class});//no parameters
            add(new Class[]{File[].class});
        }
    };

    @Override
    protected String getName() {
        return "On File Drop Event Listener";
    }

    @Override
    protected List<Class[]> methodArgumentsVariants() {
        return argumentsVariants;
    }

    @Override
    protected void attachMethod(JsonElement jsonElement, final JComponent component, final SwingsonGui gui, String propertyName, final MethodExecutor mExecutor, final int methodArgumentVariant, final ConditionAndAction conditionAndAction) {
        DropFileTransferHandler handler = new DropFileTransferHandler(new ValueEvent<File[]>() {
            @Override
            protected void valueChanged(File[] value) {
                try {
                    switch (methodArgumentVariant) {
                        case 0:
                            mExecutor.invoke(value[0]);
                            break;
                        case 1:
                            mExecutor.invoke((Object) value);
                            break;
                    }
                    runAction(conditionAndAction, gui, component);
                } catch (Throwable ex) {
                    onError(gui, ex.getCause());
                }
            }
        });

        component.setTransferHandler(handler);
    }

    private class DropFileTransferHandler extends TransferHandler {

        private final ValueEvent<File[]> valueEvent;

        public DropFileTransferHandler(ValueEvent<File[]> valueEvent) {
            this.valueEvent = valueEvent;
        }

        /**
         * @see javax.swing.TransferHandler#canImport(javax.swing.JComponent,
         * java.awt.datatransfer.DataFlavor[])
         */
        @Override
        public boolean canImport(JComponent arg0, DataFlavor[] arg1) {
            for (DataFlavor flavor : arg1) {
                if (flavor.equals(DataFlavor.javaFileListFlavor)) {
                    return true;
                }
                if (flavor.equals(DataFlavor.stringFlavor)) {
                    return true;
                }
            }
            // Didn't find any that match, so:
            return false;
        }

        /**
         * Do the actual import.
         *
         * @see javax.swing.TransferHandler#importData(javax.swing.JComponent,
         * java.awt.datatransfer.Transferable)
         */
        @Override
        public boolean importData(JComponent comp, Transferable t) {
            DataFlavor[] flavors = t.getTransferDataFlavors();
            for (DataFlavor flavor : flavors) {
                try {
                    if (flavor.equals(DataFlavor.javaFileListFlavor)) {
                        List l = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                        Iterator iter = l.iterator();
                        List<File> files = new ArrayList<>();
                        while (iter.hasNext()) {
                            File file = (File) iter.next();
                            files.add(file);
                        }

                        valueEvent.fire(files.toArray(new File[files.size()]));
                        return true;
                    } else if (flavor.equals(DataFlavor.stringFlavor)) {
                        String fileOrURL = (String) t.getTransferData(flavor);
                        try {
                            URL url = new URL(fileOrURL);
                            System.out.println("Valid URL: " + url.toString());
                            return true;
                        } catch (MalformedURLException ex) {
                            return false;
                        }
                        // now do something with the String.

                    } else {
                        // Don't return; try next flavor.
                    }
                } catch (IOException ex) {
                } catch (UnsupportedFlavorException e) {
                }
            }
            return false;
        }
    }

}
